
//--> Loth 2011 
//--> Bullet engine init

package chamans.engine
{
	import chamans.*;
	import chamans.away.*;
	import chamans.life.*;

	import away3d.entities.*;
	import away3d.materials.*;
	import away3d.primitives.*;
	import away3d.materials.methods.*;
	import away3d.containers.ObjectContainer3D;
	
	import com.bulletflash.collision.shapes.*;
	import com.bulletflash.dynamics.*;
	import com.bulletflash.plugin.away3d4.Away3D4Mesh;
	
	import flash.ui.Keyboard;
	import flash.display.*;
	import flash.events.*;
	import flash.geom.*;
	
	public class Bullet extends Sprite{
		private var BASE:Object;
		public var actif:Boolean=true;
		private var tmp:Object;
		public var world:btDynamicsWorld;
		public var Minition:int=1;
		
		private var m_player	    : Vector.<Mesh>;
		private var p_player	    : Vector.<btRigidBody>;
		private var m_ball	        : Vector.<Mesh>;
		private var p_ball	        : Vector.<btRigidBody>;
		private var m_wall	        : Vector.<Mesh>;
		private var p_wall	        : Vector.<btRigidBody>;
		private var m_room	        : Vector.<Mesh>;
		private var p_room	        : Vector.<btRigidBody>;
		private var m_pop	        : Vector.<Mesh>;
		private var p_pop	        : Vector.<btRigidBody>;
		private var m_barrel	    : Vector.<Mesh>;
		private var p_barrel	    : Vector.<btRigidBody>;
		private var m_crate	        : Vector.<Mesh>;
		private var p_crate	        : Vector.<btRigidBody>;
		private var m_plan	        : Vector.<Mesh>;
		private var p_plan	        : Vector.<btRigidBody>;
		
		public var Steps:Number=.1;
		public var times:Number=.1;
		public var MaxSteps:int=1;
		private var timeStep:Number = 1.0 / 60;
		//object import
		private var BB:barrel
		private var AA:crate
		private var Q:int
		private var matListe : Vector.<DefaultMaterialBase>;
		//private var rot:Vector3D
		private var END:Function
		private var matBall:ColorMaterial
		public var G:Number=-20;
		
		public function update( ):void
		{
			if(!actif)return;	
			UpPlayer()
			world.step(Steps, MaxSteps, times);
		}
		
		public function Bullet (base:Object, t:Number=.02, s:Number=0.03, m:int=1):void
		{
			BASE=base; times=t; Steps=s; MaxSteps=m;
			BASE.physicEngine="bullet";
			tmp=new Object();
			world = btDynamicsWorld.getInstance();
			world.initWithDbvtBroadphase();
			world.gravity=new Vector3D(0,G,0)
			matListe = new Vector.<DefaultMaterialBase>();
		}
		public function setGravity(n:Number ):void
		{
			world.gravity=new Vector3D(0,n,0);
			for each(var body:btRigidBody in world.nonStaticRigidBodies) {
				body.gravity = new Vector3D(0,n,0);
			}
		}
		public function info( ):String
		{ 
			return world.nonStaticRigidBodies.length +"|"+world.rigidBodies.length; 
		}
		//_______________________________________________Player
		public function PlayerBox():void
		{
			m_player = new Vector.<Mesh>(); 
			p_player = new Vector.<btRigidBody>();
			var N:Mesh=Make("sphere", m_player, p_player, BASE.Camera.M.baseTarget,new Vector3D(60,0,0), new Vector3D(30,.6,.6), null, false); 
			p_player[0].gravity=new Vector3D();
		}
		public function UpPlayer():void
		{
			if(p_player) p_player[0].position=BASE.Camera.M.baseTarget.add(new Vector3D(0,-100,0));
		}

		//______________________________________________//o\\ Primitive Creator
		public function Make(type:String, M:Vector.<Mesh>, P:Vector.<btRigidBody>,pos:Vector3D,  size:Vector3D, phy:Vector3D, Object:Mesh=null, visible:Boolean=true, rot:Vector3D=null):Mesh
		{
			var body : Mesh
			var map:ColorMaterial = new ColorMaterial(0xFF3333, .8);
			if(!Object){
				switch(type){
					case "plane": body = new Plane( map,size.x,size.y ); break;
					case "box": body = new Cube( map,size.x,size.y,size.z ); break;
					case "sphere": body = new Sphere( map, size.x, 16, 12, true); break;
					case "cylindre": body = new Cylinder( map, size.x, size.y, size.z, 24, 1, true); break;
					case "cone": body =  new Cone( map, size.x, size.z); break;
					
				}
				if(visible)BASE.view.scene.addChild(body)
			}
			else body = Object;
			var shape:btShape 
			switch(type){
				case "plane": shape = new btStaticPlaneShape(new Vector3D(0, 0, -1)); break;
				case "box": shape = new btBoxShape(size.x,size.y,size.z); break;
				case "sphere":  shape = new btSphereShape(size.x); break;
				case "cylindre": shape  = new btCylinderShape( size.x, size.z); break;
				case "cone": shape  = new btConeShape( size.x, size.z); break;	
				case "chair":  shape  = Perfect_Chair(); break;
				case "desk":  shape  = Perfect_Desk(); break;
				case "f":  shape  = Perfect_FATC(0); break;
				case "a":  shape  = Perfect_FATC(1); break;
				case "t":  shape  = Perfect_FATC(2); break;
				case "c":  shape  = Perfect_FATC(3); break;
				
			}
			var rigidbody:btRigidBody = new btRigidBody(shape, new Away3D4Mesh(body),phy.x);
			rigidbody.restitution = phy.z;
			rigidbody.friction = phy.y;
			rigidbody.position = pos;
			if(type=="plane"){
				var rota:Matrix3D = new Matrix3D();
				rota.appendRotation( 90, new Vector3D(1, 0, 0));
				rigidbody.rotation = rota;
			}
			if(rot){
				var rotar:Matrix3D = new Matrix3D();
				rotar.appendRotation( rot.x, new Vector3D(1, 0, 0));
				rotar.appendRotation( rot.y, new Vector3D(0, 1, 0));
				rotar.appendRotation( rot.z, new Vector3D(0, 0, 1));
				rigidbody.rotation = rotar;
			}
			P.push(rigidbody);
			M.push(body);
			world.addRigidBody(rigidbody);
			return body;
		}
		//____________________________________________________simple plane
	 	public function add_Plan(f:Number=.6, r:Number=.6):void
		{
			m_plan = new Vector.<Mesh>(); 
			p_plan = new Vector.<btRigidBody>();
			var T2:Mesh=Make("plane", m_plan, p_plan, new Vector3D(), new Vector3D(), new Vector3D(0,f,r), null, false );
		}
		
		
		//// Special bullet labs 
		//__________________________________________________Room physics definition
		public function RoomPhysics(w:int=4000, d:int=4000, h:int=3000, e:int=100):void
		{
			var debug1:Boolean=false;
			var debug2:Boolean=false;
			m_room = new Vector.<Mesh>(); 
			p_room = new Vector.<btRigidBody>();
			var phyData:Vector3D=new Vector3D(0, .8, .3);
			var ground:Mesh=Make("box",m_room, p_room, new Vector3D(0, -e/2, 0), new Vector3D( w, e, d), phyData, null,false);
			var top:Mesh=Make("box",m_room, p_room, new Vector3D(0,2450, 0), new Vector3D(w+e, 900, d), phyData, null,false);
			var b1:Mesh=Make("box",m_room, p_room, new Vector3D(-1800, h/4, (-d/2)-(e/2)), new Vector3D( 800, h/2, e), phyData, null,debug1);
			var b2:Mesh=Make("box",m_room, p_room, new Vector3D(1800, h/4, (-d/2)-(e/2)), new Vector3D( 800, h/2, e), phyData, null,debug1);
			var b3:Mesh=Make("box",m_room, p_room, new Vector3D(0, 2250, (-d/2)-(e/2)), new Vector3D( w+(e*2), h/2, e), phyData, null,debug1);
			
			var front:Mesh=Make("box",m_room, p_room, new Vector3D(0, h/2, d/2+(e/2)), new Vector3D(w+(e*2), h, e), phyData, null,debug1);
			var left:Mesh=Make("box",m_room, p_room, new Vector3D((-w/2)-e/2, h/2, 0), new Vector3D( e, h, d), phyData, null,debug1);
			var right:Mesh=Make("box",m_room, p_room, new Vector3D((w/2)+e/2, h/2, 0), new Vector3D( e, h, d), phyData, null,debug1);
			//font pieces
			var lup:Mesh=Make("box",m_room, p_room, new Vector3D(-1200, 100, -1200), new Vector3D(1600, 200, 1600), phyData,null,false);
			var rup:Mesh=Make("box",m_room, p_room, new Vector3D(1200, 100, -1200), new Vector3D( 1600, 200, 1600), phyData,null,false);
			var mup:Mesh=Make("box",m_room, p_room, new Vector3D(0, 100, -1400), new Vector3D( 800, 200, 1200), phyData,null,false);
			var staire:Mesh=Make("box",m_room, p_room, new Vector3D(0, 8.7, -645), new Vector3D( 800, 200, 450), phyData,null,false,new Vector3D(27, 0, 0) );
			//top rampe
			var lup0:Mesh=Make("box",m_room, p_room, new Vector3D(-1200, 250, -405), new Vector3D(1600, 100, 10), phyData,null,false);
			var rup0:Mesh=Make("box",m_room, p_room, new Vector3D(1200, 250, -405), new Vector3D( 1600, 100, 10), phyData,null,false);
			var lup1:Mesh=Make("box",m_room, p_room, new Vector3D(-405, 250, -605), new Vector3D(10, 100, 390), phyData,null,false);
			var rup1:Mesh=Make("box",m_room, p_room, new Vector3D(405, 250, -605), new Vector3D( 10, 100, 390), phyData, null,false);
			//var cercle:Mesh=Make("cylindre",m_room, p_room, new Vector3D(1600, 25, 800), new Vector3D( 400, 400, 50), phyData, null,false);
			//var cercle2:Mesh=Make("cylindre",m_room, p_room, new Vector3D(1600, 1095, 800), new Vector3D( 400, 400, 100), phyData, null,false);
			
			var mupX:Mesh=Make("box",m_room, p_room, new Vector3D(0, 100, -3560), new Vector3D( 10240, 200, 3120), phyData,null,debug2);
			var mupX2:Mesh=Make("box",m_room, p_room, new Vector3D(0, 100, 3560), new Vector3D( 10240, 200, 3120), phyData,null,debug2);
			
			var muuX:Mesh=Make("box",m_room, p_room, new Vector3D(-3560, 100, 0), new Vector3D( 3120, 200, 4000), phyData,null,debug2);
			var muuX2:Mesh=Make("box",m_room, p_room, new Vector3D(3560, 100, 0), new Vector3D( 3120, 200, 4000), phyData,null,debug2);
		}
		//________________________________________barrel 
		private function add_Barrel(n:int=1):void
		{
			m_barrel = new Vector.<Mesh>(); 
			p_barrel = new Vector.<btRigidBody>();
			BB = new barrel(BASE, end_Barrel)
		}
		private function end_Barrel():void
		{
			BB.Fin=Physic_Barrel
			for (var i:int=0;i<8; ++i){
				BB.clone()
			}
			BB.Del()
		}
		private function Physic_Barrel(m:Mesh, pos:Vector3D=null):void
		{
			var phyData:Vector3D=new Vector3D(2, .8, .3)
			var position:Vector3D = pos || new Vector3D(-200,100,300)
			var T2:Mesh=Make("cylindre", m_barrel, p_barrel, position, new Vector3D(30,30,88), phyData, m)
		}
		//_________________________________________crate
		public function add_Crate(F:Function=null):void
		{
			tmp['crate']= F || new Function() 
			AA = new crate(BASE, init_Crate)
		}
		private function init_Crate(m:Mesh=null):void
		{
			AA.end = physic_Crate
			BrickWall(8, 5, 1, 100, 100, 100, 1)
		}
		private function physic_Crate(m:Mesh, pos:Vector3D=null):void
		{
			var phyData:Vector3D=new Vector3D(2, .8, .3);
			var position:Vector3D = pos || new Vector3D();
			var size:Vector3D=new Vector3D(100,100,100);
			var R:int=BASE.TOOL.Ran(3);
			var Rota:Vector3D;
			if(R==0)Rota=new Vector3D(0,0,0);
			if(R==1)Rota=new Vector3D(0,90,0);
			if(R==2)Rota=new Vector3D(0,180,0);
			if(R==3)Rota=new Vector3D(0,270,0);
			var T2:Mesh=Make("box", m_crate, p_crate, position, size, phyData, m, false, Rota);
		}
		private function BrickWall(numX:int=8, numY:int=5, numZ:int=1, w:int=80, h:int=180, d:int=60, decal:int=2):void
		{
			m_crate = new Vector.<Mesh>(); 
			p_crate = new Vector.<btRigidBody>();
			var phyData:Vector3D=new Vector3D(10, .3, .3);
			var pos :Vector3D;
			for (var z:int=0;z<numZ;z++ ) {
				for (var y:int=0;y<numY;y++) {
					for (var x:int=0;x<numX;x++) {
						pos= new Vector3D(-w+(x*(w+decal)),h+(y*(h+decal)),d-(z*(d+decal)));
						AA.clone(pos);
					}}}
			tmp['crate'](); tmp['crate']=null;
		}
		//_____________________________________________________Gun shoot
		public function activeGUN(B:Boolean=false) : void
		{
			if(B){
				m_ball = new Vector.<Mesh>(); 
				p_ball = new Vector.<btRigidBody>();	
				BASE.stage.addEventListener(MouseEvent.MOUSE_DOWN, GunMouseDown);
				PlayerBox()
			}
			else BASE.stage.removeEventListener(MouseEvent.MOUSE_DOWN, GunMouseDown);
		}
		private function GunMouseDown(event : MouseEvent) : void
		{
			if(!BASE.Camera.mouseback)return;
			// calculate impluse
			var pos : Vector3D 
			var mpos : Vector3D
			if(BASE.Camera.M.gun) {
				pos=BASE.view.camera.position
				mpos= BASE.Camera.target.position;
			}
			else {pos=BASE.Camera.M.baseTarget;  mpos= BASE.Camera.M.gunTarget;}
			var impulse : Vector3D = mpos.subtract(pos);
			impulse.normalize();
			impulse.scaleBy(250);
			var R:Vector3D =new Vector3D( BASE.Camera.M.H-90, BASE.Camera.M.V-90, 0)
			
			add_ball(  pos, mpos, impulse, R)
		}
		public function add_ball(v1:Vector3D, v2:Vector3D, v3:Vector3D, R:Vector3D):void
		{
			if(!matBall){
				matBall=new ColorMaterial(0xAAAAAA);
				matBall.lights = BASE.LIGHT;
				if(BASE.reflect)BASE.F_reflect(matBall, .6);
				if(BASE.fog)BASE.F_Fog(matBall);
				matBall.specular = 1;
				matBall.gloss = 30;
			}
			
			if(m_ball.length>10)Delete(m_ball, p_ball)
			
			var N:Mesh;
			switch(Minition){
				case 0: N=Make("box", m_ball, p_ball, v1,new Vector3D(50,50,50), new Vector3D(5,.6,.6)); break;
				case 1: N=Make("sphere", m_ball, p_ball, v1,new Vector3D(30,0,0), new Vector3D(5,.6,.6)); break;
				case 2: N=Make("cylindre", m_ball, p_ball, v1,new Vector3D(25,25,50), new Vector3D(5,.6,.6)); break;
				case 3: N=Make("cone", m_ball, p_ball, v1,new Vector3D(25,0,50), new Vector3D(5,.6,.6)); break;
			}
			var rot:Matrix3D = new Matrix3D();
			if(Minition==2 || Minition==3)rot.appendRotation( -(R.x-90), new Vector3D(1, 0, 0));
			else rot.appendRotation( -R.x, new Vector3D(1, 0, 0));
			rot.appendRotation( R.y, new Vector3D(0, 1, 0));
			p_ball[p_ball.length-1].rotation = rot;
			N.material=matBall;
			p_ball[p_ball.length-1].applyCentralImpulse(v3);
		}
		
		public function Delete(M:Vector.<Mesh>, P:Vector.<btRigidBody>):void
		{
			while(M.length>0){
				BASE.view.scene.removeChild(M[M.length-1]);
				world.removeRigidBody(P[M.length-1]);
				P.pop();
				M.pop();
		}}
		
		//___________________________________________________Complex mesh definition
		private function Perfect_Chair():btCompoundShape 
		{
			var def:Array=[38, 7, 4, 43, 17, 20.5, 21.5];
			var boxShape1:btBoxShape = new btBoxShape(def[0], def[1], 45);
			var boxShape2:btBoxShape = new btBoxShape(def[2], def[3], def[2]);
			var boxShape3:btBoxShape = new btBoxShape(def[2], def[3], def[2]);
			var boxShape4:btBoxShape = new btBoxShape(def[2], def[3], def[2]);
			var boxShape5:btBoxShape = new btBoxShape(def[2], def[3], def[2]);
			var boxShape6:btBoxShape = new btBoxShape(def[2], def[3], def[2]);
			var boxShape7:btBoxShape = new btBoxShape(def[2], def[3], def[2]);
			var boxShape8:btBoxShape = new btBoxShape(38, 12, 4);
			var decal:int=def[4];
			var decal2:int=def[5];
			var decal3:int=def[6];
			var chairShape:btCompoundShape = new btCompoundShape();
			chairShape.addChildShape(boxShape1, new Vector3D(0, 3.5, 0), new Matrix3D());
			chairShape.addChildShape(boxShape2, new Vector3D(-decal,-decal3,-decal2), new Matrix3D());
			chairShape.addChildShape(boxShape3, new Vector3D(decal, -decal3, -decal2), new Matrix3D());
			chairShape.addChildShape(boxShape4, new Vector3D(decal, -decal3, decal2), new Matrix3D());
			chairShape.addChildShape(boxShape5, new Vector3D( -decal, -decal3, decal2), new Matrix3D());
			chairShape.addChildShape(boxShape6, new Vector3D(decal, decal3, decal2), new Matrix3D());
			chairShape.addChildShape(boxShape7, new Vector3D( -decal, decal3, decal2), new Matrix3D());
			chairShape.addChildShape(boxShape8, new Vector3D( 0,36.5, decal2), new Matrix3D());
			return chairShape;
		}
		private function Perfect_Desk():btCompoundShape
		{
			var boxShape1:btBoxShape = new btBoxShape(130, 14, 70);
			var boxShape2:btBoxShape = new btBoxShape(4, 60, 4);
			var boxShape3:btBoxShape = new btBoxShape(4, 60, 4);
			var boxShape4:btBoxShape = new btBoxShape(4, 60, 4);
			var boxShape5:btBoxShape = new btBoxShape(4, 60, 4);
			var decal:int=63;
			var decal2:int=33;
			var decal3:int=7;
			var deskShape:btCompoundShape = new btCompoundShape();
			deskShape.addChildShape(boxShape1, new Vector3D(0, 30, 0), new Matrix3D());
			deskShape.addChildShape(boxShape2, new Vector3D(-decal,-decal3,-decal2), new Matrix3D());
			deskShape.addChildShape(boxShape3, new Vector3D(decal, -decal3, -decal2), new Matrix3D());
			deskShape.addChildShape(boxShape4, new Vector3D(decal, -decal3, decal2), new Matrix3D());
			deskShape.addChildShape(boxShape5, new Vector3D( -decal, -decal3, decal2), new Matrix3D());
			return deskShape;
		}
		private function  Perfect_FATC(n:int=0):btCompoundShape 
		{
			var boxShape1:btBoxShape = new btBoxShape(120, 140, 40);
			var boxShape2:btBoxShape
			var boxShape3:btBoxShape 
			var deskShape:btCompoundShape = new btCompoundShape();
			if (n==1 || n==3)	deskShape.addChildShape(boxShape1, new Vector3D(0, 0, 0), new Matrix3D());
			else if (n==0) {//F
				boxShape1= new btBoxShape(40, 140, 40);
				boxShape2= new btBoxShape(80, 20, 40);
				boxShape3= new btBoxShape(50, 20, 40);
				deskShape.addChildShape(boxShape1, new Vector3D(40, 0, 0), new Matrix3D());
				deskShape.addChildShape(boxShape2, new Vector3D(-20, 60, 0), new Matrix3D());
				deskShape.addChildShape(boxShape3, new Vector3D(-5, 0, 0), new Matrix3D());
			}
			else {//T
				boxShape1= new btBoxShape(40, 140, 40);
				boxShape2= new btBoxShape(120, 20, 40);
				deskShape.addChildShape(boxShape1, new Vector3D(0, 0, 0), new Matrix3D());
				deskShape.addChildShape(boxShape2, new Vector3D(0, 60, 0), new Matrix3D());
			}
			return deskShape;
		}
		
		
}}